#include "Time.h"
#include <time.h>
#include <string.h>
#include <assert.h>

#ifdef __WINDOWS__
#include <Windows.h>
#elif __LINUX__
#include <sys/time.h>
#endif

#define DEFAULT_TIME_FMT "%Y-%m-%d %H:%M:%S"
#define TIMESTRLEN 512
char g_szTime[TIMESTRLEN];

void _TtToTm(struct tm& tmDst, const time_t ttSrc)
{
	memcpy(&tmDst, localtime(&ttSrc), sizeof(struct tm));
}

void TimeManager::UpdateTmpTime( uint uTime )
{
	m_uTmpTime = uTime;
	_TtToTm(*m_ptmTmpTime, uTime);
}

uint _GetTick()
{
#ifdef __WINDOWS__
	return GetTickCount();
#elif __LINUX__
	struct timeval current;
	gettimeofday(&current, NULL);
	return uint((uint64)current.tv_sec * 1000 + (uint64)current.tv_usec / 1000);
#endif
}

uint64 _GetTick2()
{
	time_t tT;
	uint   uSec;
#if defined(__WINDOWS__)
	struct tm tM;
	SYSTEMTIME stm;
	GetLocalTime(&stm);
	tM.tm_year = stm.wYear  - 1900;
	tM.tm_mon  = stm.wMonth - 1;
	tM.tm_mday = stm.wDay;
	tM.tm_hour = stm.wHour;
	tM.tm_min  = stm.wMinute;
	tM.tm_sec  = stm.wSecond;
	tT          = mktime(&tM);
	uSec        = stm.wMilliseconds;
#elif defined(__LINUX__)
	struct timeval tv;
	struct timezone tz;
	gettimeofday(&tv, &tz);
	tt          = tv.tv_sec;
	uSec        = tv.tv_usec;
#endif
	return tT*1000+uSec;
}
void _Sleep(uint ms)
{
#ifdef __WINDOWS__
	Sleep(ms); 
#elif __LINUX__
	usleep( ms * 1000);
#endif
}

void _Sleep2(uint millisecond)
{
#if defined(__WINDOWS__)
	Sleep( millisecond );
#elif defined(__LINUX__)
	struct timespec tp1, tp2;
	tp1.tv_sec = uint(millisecond/1000);
	tp1.tv_nsec = long((millisecond%1000)*1000*1000);
	tp2.tv_sec = 0;
	tp2.tv_nsec = 0;
	nanosleep( &tp1, &tp2);
#endif
}

void TimeManager::Init()
{
	if ( m_ptmNowTime == NULL )
		m_ptmNowTime = new tm;
	if ( m_ptmTmpTime == NULL )
		m_ptmTmpTime = new tm;
	assert(m_ptmNowTime && m_ptmTmpTime);
	m_uStartTick = _GetTick();
	Update();
}

void TimeManager::Update()
{
	m_uNowTime = (uint)time(NULL);
	_TtToTm(*m_ptmNowTime, m_uNowTime);
}

TimeManager::~TimeManager()
{
	if ( m_ptmNowTime )
	{
		delete m_ptmNowTime;
		m_ptmNowTime = NULL;
	}
	if ( m_ptmTmpTime )
	{
		delete m_ptmTmpTime;
		m_ptmTmpTime = NULL;
	}
}

uint TimeManager::GetTick()
{
	return _GetTick()-m_uStartTick;
}

uint64 TimeManager::GetTick2()
{
	return _GetTick2();
}

uint TimeManager::GetTime()
{ 
	return (uint)m_uNowTime;
}

uint TimeManager::TimeChange(struct tm& tmSrc)
{ 
	return (uint)mktime(&tmSrc);
}

void TimeManager::TimeChange(struct tm& tmDst, uint& ttSrc)
{ 
	_TtToTm(tmDst, (time_t)ttSrc);
}

uint TimeManager::TimeChange(uint uYear, uint uMon, uint uDay, uint uHour, uint uMin, uint uSec)
{
	struct tm tM;
	tM.tm_year = uYear-1900;
	tM.tm_mon  = uMon - 1;
	tM.tm_mday = uDay;
	tM.tm_hour = uHour;
	tM.tm_min  = uMin;
	tM.tm_sec  = uSec;
	tM.tm_isdst= -1;
	uint uTime = (uint)mktime(&tM);
	return uTime;
}

const char* TimeManager::GetStrTime(const char* fmt)
{
	if ( fmt == NULL )
		fmt = DEFAULT_TIME_FMT;
	if ( strftime(g_szTime, TIMESTRLEN, fmt, m_ptmNowTime) )
		return g_szTime;
	return NULL;
}

const char* TimeManager::GetStrTime(uint tT,const char* fmt)
{
	if ( fmt == NULL )
		fmt = DEFAULT_TIME_FMT;
	if ( tT != m_uTmpTime )
		UpdateTmpTime(tT);
	if ( strftime(g_szTime, TIMESTRLEN, fmt,m_ptmTmpTime) )
		return g_szTime;
	return NULL;
}

const char* TimeManager::GetStrTime(struct tm* tM,const char* fmt)
{
	assert(tM);
	if ( fmt == NULL )
		fmt = DEFAULT_TIME_FMT;
	if ( strftime(g_szTime, TIMESTRLEN, fmt, tM) )
		return g_szTime;
	return NULL;
}
uint TimeManager::GetYear(uint uTime)
{
	if ( uTime == 0 )
		return m_ptmNowTime->tm_year+1900;
	if ( uTime != m_uTmpTime )
		UpdateTmpTime(uTime);
	return m_ptmTmpTime->tm_year+1900;
}

uint TimeManager::GetMon(uint uTime)
{
	if ( uTime == 0 )
		return m_ptmNowTime->tm_mon+1;
	if ( uTime != m_uTmpTime )
		UpdateTmpTime(uTime);
	return m_ptmTmpTime->tm_mon+1;
}

uint TimeManager::GetDay(uint uTime)
{
	if ( uTime == 0 )
		return m_ptmNowTime->tm_mday;
	if ( uTime != m_uTmpTime )
		UpdateTmpTime(uTime);
	return m_ptmTmpTime->tm_mday;
}

uint TimeManager::GetHour(uint uTime)
{
	if ( uTime == 0 )
		return m_ptmNowTime->tm_hour;
	if ( uTime != m_uTmpTime )
		UpdateTmpTime(uTime);
	return m_ptmTmpTime->tm_hour;
}

uint TimeManager::GetMin(uint uTime)
{
	if ( uTime == 0 )
		return m_ptmNowTime->tm_min;
	if ( uTime != m_uTmpTime )
		UpdateTmpTime(uTime);
	return m_ptmTmpTime->tm_min;
}

uint TimeManager::GetSec(uint uTime)
{
	if ( uTime == 0 )
		return m_ptmNowTime->tm_sec;
	if ( uTime != m_uTmpTime )
		UpdateTmpTime(uTime);
	return m_ptmTmpTime->tm_sec;
}

void TimeManager::Sleep( uint ms )
{
	_Sleep(ms);
}

void TimeManager::Sleep2( uint ms )
{
	_Sleep2(ms);
}
